Imports System.Net.Sockets
Imports System.Windows.Forms

Public Class LocalPort

	Implements IDisposable

	'====================================================================

	Public Event EstablishedConnection(ByVal UserName As String, ByVal UserAddress As String, ByVal ExistingConnection As UserConnection)

	'====================================================================

	Private ListenerThread As Threading.Thread
	Private Listener As TcpListener

	'====================================================================

#Region " Constructors and destructors "

	Public Sub New()
		ListenerThread = New Threading.Thread(AddressOf DoListen)
		ListenerThread.Start()
	End Sub

	Public Sub Dispose() Implements System.IDisposable.Dispose
		If Not ListenerThread Is Nothing Then
			Try
				Listener.Stop()
				ListenerThread.Abort()
			Catch e As Exception
				' do nothing
			End Try
			ListenerThread = Nothing
		End If
	End Sub

	Protected Overrides Sub Finalize()
		MyBase.Finalize()
		Dispose()
	End Sub

#End Region

	'====================================================================
	' Listening
	'====================================================================

	' This subroutine is used as a background listener thread to allow reading incoming
	' messages without lagging the user interface.
	Private Sub DoListen()
		Try
			' Start listen for new connections. 
			' Executes once when program started till its termination.
			Listener = New TcpListener(System.Net.IPAddress.Any, PortNum)

			' Once in program's lifetime
			Listener.Start()

		Catch e As Exception
			MessageBox.Show("Error initializing port listener: " & e.Message)
			Return
		End Try

		' Main loop of the Listener thread.
		Do While Not ListenerThread Is Nothing
			Try
				' AcceptTcpClient waits till a new client knocks at the door (port)
				' and returns it.
				' UserConnection is a wrapper class for TcpClient.
				Dim NewUserConnection As UserConnection = _
				 New UserConnection(Listener.AcceptTcpClient())

				' Add a temporary event handler to catch the initiating message.
				AddHandler NewUserConnection.LineReceived, AddressOf ReceivedCallback

			Catch e As Exception
				' We catch this when thread aborts
			End Try
		Loop
	End Sub

	'====================================================================
	' Callback function of the Listener thread. The first message of every new incoming TcpClient
	' is received by this callback.
	'====================================================================

	Private Sub ReceivedCallback(ByVal Sender As UserConnection, ByVal Data As String)
		' Stop catching further messages from this client.
		RemoveHandler Sender.LineReceived, AddressOf ReceivedCallback

		'====================================================================
		' Data is expected to be in the following format:
		' CONNECT|UserName|UserAddress"
		' Parse the message.
		Dim Tokens As String() = Data.Split("|"c)		  '     "|"c means char '|' in VB.NET

		If Tokens.Length <> 3 OrElse Tokens(0) <> msgConnect Then
			Throw New Exception("Incorrect message received:" & ControlChars.CrLf & Data)
		End If

		Dim Name As String = Tokens(1)
		Dim Address As String = Tokens(2)
		'====================================================================

		RaiseEvent EstablishedConnection(Name, Address, Sender)
	End Sub

End Class
